package com.hadron.media.slideshow 
{
	import com.hadron.media.slideshow.enum.SlideshowStatus;
	import com.hadron.media.slideshow.events.SlideshowEvent;
	import com.hadron.media.slideshow.events.SlideshowModelEvent;
	import com.hadron.media.slideshow.items.ISlideshowItem;
	import com.hadron.media.slideshow.patterns.mvc.model.ISlideshowModel;
	import com.hadron.media.slideshow.patterns.mvc.model.SlideshowModel;
	import com.hadron.media.slideshow.patterns.mvc.view.SlideshowView;
	import flash.display.MovieClip;
	import temple.core.CoreSprite;
	import temple.data.collections.ICollection;
	import temple.data.loader.preload.IPreloader;

	/**
	 * 2011-03-09 12:23
	 * @author Hadron
	 */
	public class Slideshow extends CoreSprite implements ISlideshow
	{
		/** @private */
		private var _preloader:IPreloader;
		
		private var model:ISlideshowModel;
		private var view:SlideshowView;
		
		/** @private */
		private var _version:String = "VER. 1.0";
		public var avatar:MovieClip;
		
		/** @private */
		private var _listenerTypes:Object = { onItemInComplete: "itemInComplete", 
									   onItemOutComplete: "itemOutComplete",
									   onItemChange: "itemChange",
									   onItemsLoadComplete: "itemsLoadComplete",
									   onStatusChange: "statusChange"};
		
		/** 
		 * An object containing optional configuration details, 
		 * typically passed through a constructor parameter. 
		 */
		public var vars:Object;
		
		/**
		 * Slideshow Constructor
		 * @param	vars raw objetct or stongly typed SlideshowVars object
		 * @return Slideshow instance
		 */
		public function Slideshow(vars:Object = null)
		{
			super();
			init();
			
			//call all available setters
			this.vars = (vars) ? vars : null;
			if (this.vars) {
				initVars();
			}
		}
		
		private function initVars():void 
		{
			if (this.vars.isSlideshowVars) { 
				this.vars = vars.vars;
			}
			
			// read slideshowVars or set default parameters 
			model.autoPlay = (this.vars.autoPlay != undefined) ? Boolean(this.vars.autoPlay) : false;
			model.autoLoad = (this.vars.autoLoad != undefined) ? Boolean(this.vars.autoLoad) : true;
			model.displayTime = (this.vars.displayTime != undefined) ? Number(this.vars.displayTime) : 2;
			model.fadeTime = (this.vars.fadeTime != undefined) ? Number(this.vars.fadeTime) : .5;
			model.currentIndex = (this.vars.currentIndex != undefined) ? uint(this.vars.currentIndex) : 0;
			model.debug = (this.vars.debug != undefined) ? Boolean(this.vars.debug) : false;
			model.background = (this.vars.background != undefined) ? Boolean(this.vars.background) : true;
			model.backgroundColor = (this.vars.backgroundColor != undefined) ? uint(this.vars.backgroundColor) : 0x000000;
			model.backgroundAlpha = (this.vars.backgroundAlpha != undefined) ? Number(this.vars.backgroundAlpha) : 1;
			model.xmlURL = (this.vars.xmlURL != undefined) ? String(this.vars.xmlURL) : null;
			
			// assign listeners to object when needed
			for (var p:String in _listenerTypes) {
				if (p in this.vars && this.vars[p] is Function) {
					this.addEventListener(_listenerTypes[p], this.vars[p]);
				}
			}
		}
		
		private function init():void
		{
			//set version and component name
			avatar.nameTF.text = "SS";
			avatar.verTF.text = _version;
			avatar.visible = false;
			
			// init MVC
			model = new SlideshowModel();
			model.addEventListener(SlideshowModelEvent.ITEM_CHANGE, handleItemChange);
			view = new SlideshowView(model);
			addChild(view);
		}
		
		private function handleItemChange(e:SlideshowModelEvent):void 
		{
			dispatchEvent(new SlideshowEvent(SlideshowEvent.ITEM_CHANGE));
		}
		
		/* --------------------------------  GETTERS / SETTERS -------------------------------  */
		/* INTERFACE temple.ui.IHasBackground */
		public function get background():Boolean { return model.background; }
		[Inspectable(defaultValue=false)]
		public function set background(value:Boolean):void { model.background = value; }
		
		public function get backgroundColor():uint { return model.backgroundColor; };
		[Inspectable(defaultValue=0x000000)]
		public function set backgroundColor(value:uint):void { model.backgroundColor = value; }
		
		public function get backgroundAlpha():Number { return model.backgroundColor; }
		[Inspectable(defaultValue=1)]
		public function set backgroundAlpha(value:Number):void { model.backgroundAlpha = value; }
		
		/* INTERFACE temple.debug.IDebuggable*/
		public function set debug(value:Boolean):void {	model.debug = value; }
		public function get debug():Boolean { return model.debug; }
		
		public function get status():SlideshowStatus { return model.status; }
		
		/* INTERFACE temple.data.loader.preload.IPreloadable*/
		public function set preloader(value:IPreloader):void { _preloader = value; }
		public function get preloader():IPreloader { return _preloader; }
		
		/* INTERFACE components.slideshow.ISlideshow */
		public function get autoPlay():Boolean { return model.autoPlay; }
		[Inspectable(defaultValue=false)]
		public function set autoPlay(value:Boolean):void { model.autoPlay = value; }
		
		public function get autoLoad():Boolean { return model.autoLoad; }
		[Inspectable(defaultValue=false)]
		public function set autoLoad(value:Boolean):void { model.autoLoad = value; }
		
		public function get displayTime():Number { return model.displayTime;	}
		[Inspectable(defaultValue=5)]
		public function set displayTime(value:Number):void { model.displayTime = value;	}
		
		public function get fadeTime():Number {	return model.fadeTime; }
		[Inspectable(defaultValue=2)]
		public function set fadeTime(value:Number):void { model.fadeTime = value; }
		
		public function get currentIndex():uint { return model.currentIndex;	}
		[Inspectable(defaultValue=0)]
		public function set currentIndex(value:uint):void { model.currentIndex = value; }
		
		public function get numItems():uint { return model.items.length; };
		public function get items():ICollection { return model.items; };
		
		
		public function set data(value:Array):void
		{
			//make sure all garbage have been cleanedUp before you set new data!
			cleanUp();
		}
		[Inspectable(defaultValue="")]
		public function set xmlURL(value:String):void {	model.xmlURL = value; }
		public function get xmlURL():String { return model.xmlURL; }
		
		/* --------------------------------  PUBLIC METHODS ----------------------------------  */
		
		public function start(startIndex:uint = 0):void
		{
			model.currentIndex = startIndex;
			model.status = SlideshowStatus.PLAYING;
			dispatchEvent(new SlideshowEvent(SlideshowEvent.STATUS_CHANGE));
		}
		
		public function stop():void
		{
			if (model.status == SlideshowStatus.PLAYING)
			{
				model.status = SlideshowStatus.STOPPED;
				dispatchEvent(new SlideshowEvent(SlideshowEvent.STATUS_CHANGE));
			}
		}
		
		public function cleanUp():void
		{
			//model cleanUp
			model.clear();
			//TODO: view cleanUp
			view.clear();
			//TODO: this cleanUp
				
		}
		
		public function showItemAt(value:uint, useItemTransition:Boolean = true):ISlideshowItem
		{
			model.currentIndex = value;
			//if you wish to perform different transition in on given item - set useItemTransition to false
			// it will prevent from duplicating or cross animating certain effects and dispatch its TRANSITION_IN_COMPLETE event immediately
			if (useItemTransition) {
				model.transition = true;
			}else {
				model.transition = false;
				dispatchEvent(new SlideshowEvent(SlideshowEvent.ITEM_IN_COMPLETE));
			}
			
			return model.currentItem;
		}
		
		public function showItemByURL(url:String, useItemTransition:Boolean = true):ISlideshowItem
		{
			model.currentItem = model.itemsByURL[url];
			if (useItemTransition) {
				model.transition = true;
			} else {
				model.transition = false;
				dispatchEvent(new SlideshowEvent(SlideshowEvent.ITEM_IN_COMPLETE));
			}
			return model.currentItem;
		}
		
		public function showItemByName(name:String, useItemTransition:Boolean = true):ISlideshowItem
		{
			model.currentItem = model.itemsByName[name];
			if (useItemTransition) {
				model.transition = true;
			} else {
				model.transition = false;
				dispatchEvent(new SlideshowEvent(SlideshowEvent.ITEM_IN_COMPLETE));
			}
			return model.currentItem;
		}
		
		public function load():void
		{
			//change status
			model.status = SlideshowStatus.LOADING;
			dispatchEvent(new SlideshowEvent(SlideshowEvent.STATUS_CHANGE));
			if (preloader)
				preloader.onLoadStart();
			model.load();
		}
		
		/* ----------------  PRIVATE/PROTECTED METHODS --------------------  */
		private function showNext():void
		{
			model.currentIndex++;
			if (model.currentIndex > items.length - 1) model.currentIndex = 0;
		}
	}
}